<?php
/**
 * Created by PhpStorm.
 * User: My
 * Date: 2018/2/25
 * Time: 15:09
 */

namespace RjgcPay\WxPcPay;

use RjgcPay\PayModeInterface;
use RjgcPay\WxPcPay\buildermodel\WxPayTradePagePayContentBuilder;


/**
 * 微信支付处理类-扫描支付（PC）
 *
 * @package RjgcPay\WxPcPay
 */
class PayMode implements PayModeInterface
{

    private $app_config;
    private $payMode_config;
    /**
     * 支付构造函数
     * PayMode constructor.
     * @param $app_config  自定义配置信息(外部)
     * @param $payMode_config  特定支付配置信息（内部）
     * @throws \Exception
     */
    public function __construct($app_config,$payMode_config)
    {
        require_once dirname(dirname ( __FILE__ )).'/lib/wx_sdk/lib/WxPay.Api.php';
        new Pay($app_config,$payMode_config);
        $this->app_config=$app_config;
        $this->payMode_config=$payMode_config;
    }


    /**
     * 统一付款接口
     *
     * @param $data  支付需要提供的参数
     * @return bool|mixed|\SimpleXMLElement|string|\提交表单HTML文本
     */
    public function unifiedPay($data='')
    {

        //验证订单参数
        if ($data['model_type']==1){
            if (!empty($this->app_config['payment']['pc_pay_notify_url_one']) && trim($this->app_config['payment']['pc_pay_notify_url_one']) != "") {
                \WxPayConfig::$NOTIFY_URL = $this->app_config['payment']['pc_pay_notify_url_one'];  //
            }
            elseif (!empty($this->app_config['payment']['notify_url']) && trim($this->app_config['payment']['notify_url']) != ""){
                \WxPayConfig::$NOTIFY_URL = $this->app_config['payment']['notify_url'];  //
            }
            elseif (!empty($this->payMode_config['notify_url_one']) && trim($this->payMode_config['notify_url_one']) != ""){
                \WxPayConfig::$NOTIFY_URL = $this->payMode_config['notify_url_one'];  //
            }
            elseif (!empty($this->payMode_config['notify_url']) && trim($this->payMode_config['notify_url']) != ""){
                \WxPayConfig::$NOTIFY_URL = $this->payMode_config['notify_url'];  //
            }
            else {
                throw new \Exception("商户支付回调地址必填");
            }

            if (empty($data['product_id'])||$data['product_id']==""){
                throw new \Exception("商品标识必填（扫描方式一）");
            }


            $notify = new NativePay();
            $url1 = $notify->GetPrePayUrl($data['product_id']);

           if (empty($url1)){
               throw new \Exception("系统错误了，生成二维码失败");
           }
           else{
               return $url1;
           }

        }
        elseif ($data['model_type']==2){
            $wxPayTradePagePayContentBuilder=new WxPayTradePagePayContentBuilder($data);
            if (!empty($this->app_config['payment']['pc_pay_notify_url_two']) && trim($this->app_config['payment']['pc_pay_notify_url_two']) != "") {
                \WxPayConfig::$NOTIFY_URL = $this->app_config['payment']['pc_pay_notify_url_two'];  //
            }
            elseif (!empty($this->app_config['payment']['notify_url']) && trim($this->app_config['payment']['notify_url']) != ""){
                \WxPayConfig::$NOTIFY_URL = $this->app_config['payment']['notify_url'];  //
            }
            elseif (!empty($this->payMode_config['notify_url_two']) && trim($this->payMode_config['notify_url_two']) != ""){
                \WxPayConfig::$NOTIFY_URL = $this->payMode_config['notify_url_two'];  //
            }
            elseif (!empty($this->payMode_config['notify_url']) && trim($this->payMode_config['notify_url']) != ""){
                \WxPayConfig::$NOTIFY_URL = $this->payMode_config['notify_url'];  //
            }
            else {
                throw new \Exception("商户支付回调地址必填");
            }

            //模式二
            /**
             * 流程： WxPayUnifiedOrder  NativePay
             * 1、调用统一下单，取得code_url，生成二维码
             * 2、用户扫描二维码，进行支付
             * 3、支付完成之后，微信服务器会通知支付成功
             * 4、在支付成功通知中需要查单确认是否真正支付成功（见：notify.php）
             */

            $notify = new NativePay();
            $input = new \WxPayUnifiedOrder();
            $input->SetBody($wxPayTradePagePayContentBuilder->getBody());
            $input->SetAttach($wxPayTradePagePayContentBuilder->getSubject());
            $input->SetOut_trade_no($wxPayTradePagePayContentBuilder->getOutTradeNo());
            $input->SetTotal_fee($wxPayTradePagePayContentBuilder->getTotalAmount()*100);
            $input->SetTime_start(date("YmdHis"));
            //$input->SetTime_expire(date("YmdHis", time() + 600));
            if ($wxPayTradePagePayContentBuilder->getGoodsTag()){
                $input->SetGoods_tag($wxPayTradePagePayContentBuilder->getGoodsTag());
            }
            $input->SetNotify_url(\WxPayConfig::$NOTIFY_URL);
            $input->SetTrade_type("NATIVE");
            if ($wxPayTradePagePayContentBuilder->getProductId()){
                $input->SetProduct_id($wxPayTradePagePayContentBuilder->getProductId());
            }

            $result = $notify->GetPayUrl($input);
            //[return_code] => FAIL [return_msg] => 签名错误 )
            if (isset($result['return_code'])&&$result['return_code']=='FAIL'){
                throw new \Exception($result['return_msg']);
            }
            else{
                $url2 = $result["code_url"];

                return $url2;
            }
        }

    }


    /**
     * 统一同步通知回调处理.
     *
     * @param \RjgcPay\支付后支付平台同步返回的数据 $data
     * @return bool|mixed
     */
    public function unifiedReturnUrl($data)
    {
        print_r('开发中');die;
    }

    /**
     * 扫描方式一异步回调
     */
    public function unifiedReturnNotifyOne(){

        //和模式二使用同一个最终回调地址
        if (!empty($this->app_config['payment']['pc_pay_notify_url_two']) && trim($this->app_config['payment']['pc_pay_notify_url_two']) != "") {
            \WxPayConfig::$NOTIFY_URL = $this->app_config['payment']['pc_pay_notify_url_two'];  //
        }
        elseif (!empty($this->app_config['payment']['notify_url']) && trim($this->app_config['payment']['notify_url']) != ""){
            \WxPayConfig::$NOTIFY_URL = $this->app_config['payment']['notify_url'];  //
        }
        elseif (!empty($this->payMode_config['notify_url_two']) && trim($this->payMode_config['notify_url_two']) != ""){
            \WxPayConfig::$NOTIFY_URL = $this->payMode_config['notify_url_two'];  //
        }
        elseif (!empty($this->payMode_config['notify_url']) && trim($this->payMode_config['notify_url']) != ""){
            \WxPayConfig::$NOTIFY_URL = $this->payMode_config['notify_url'];  //
        }
        else {
            throw new \Exception("商户支付回调地址必填");
        }

        /*$notify = new NativeNotifyCallBack();
        $notify->Handle(true);*/
        /*$postString=file_get_contents("php://input");
        libxml_disable_entity_loader(true);
        $xml=simplexml_load_string($postString,'SimpleXMLElement',LIBXML_NOCDATA);*/
        //$notify = new NativeNotifyCallBack();
        //$result=$notify->unifiedorder($xml['openid'],$xml['product_id']);

        /*require \WxPayConfig::$PC_PAY_ONE_GET_ORDER;
        //统一下单
        $input = new \WxPayUnifiedOrder();
        $input->SetBody("test");
        $input->SetAttach("test");
        $input->SetOut_trade_no(\WxPayConfig::$MCHID.date("YmdHis"));
        $input->SetTotal_fee("1");
        $input->SetTime_start(date("YmdHis"));
        $input->SetTime_expire(date("YmdHis", time() + 600));
        $input->SetGoods_tag("test");
        $input->SetNotify_url(\WxPayConfig::$NOTIFY_URL);
        $input->SetTrade_type("NATIVE");
        $input->SetOpenid($xml['openid']);
        $input->SetProduct_id($xml['product_id']);
        $result = \WxPayApi::unifiedOrder($input);
        print_r($result);die;*/

        //$notify = new NativeNotifyCallBack();
        //echo $notify->Handle(true);
        $this->returnNotifyOne();


    }

    /**
     * 统一异步通知回调处理.
     *
     * @param \RjgcPay\支付后支付平台异步返回的数据 $data
     * @return bool|mixed
     */
    public function unifiedReturnNotify($data)
    {
        $notify=new PayNotifyCallBack();
        $notify->Handle(false);
    }

    /**
     * 统一收单线下交易查询.
     *
     * @param \RjgcPay\查询条件项 $data
     * @return bool|\SimpleXMLElement[]|string|\提交表单HTML文本\
     */
    public function unifiedQuery($data)
    {
        print_r('开发中');die;
        return $response;
    }


    /**
     * 统一收单交易关闭接口.
     *
     * @param \RjgcPay\关闭条件项 $data
     * @return bool|\SimpleXMLElement[]|string|\提交表单HTML文本
     */
    public function unifiedClose($data)
    {
        print_r('开发中');die;
        return $response;
    }

    /**
     * 统一收单交易退款接口.
     *
     * @param \RjgcPay\退款参数 $data
     * @return bool|\SimpleXMLElement[]|string|\提交表单HTML文本
     */
    public function unifiedRefund($data)
    {
        print_r('开发中');die;
        return $response;
    }


    /**
     * 统一收单交易退款查询.
     *
     * @param \RjgcPay\退款查询条件 $data
     * @return bool|mixed|\SimpleXMLElement|string|\提交表单HTML文本
     */
    public function unifiedRefundQuery($data)
    {
        print_r('开发中');die;
        return $response;
    }


    public function unifiedDownloadurlQuery($data)
    {
        print_r('尚未实现');
        // TODO: Implement unifiedDownloadurlQuery() method.
    }

    /**
     * 验签方法
     *
     * @param $data 验签支付宝返回的信息，使用支付宝公钥
     */
    public function check($data)
    {
        print_r('开发中');die;
        return $result;
    }

    /**
     * 写入日志.
     *
     * @param $text
     */
    public function writeLog($text)
    {
        print_r('开发中');die;
        file_put_contents ( dirname ( __FILE__ ).DIRECTORY_SEPARATOR."./../../log.txt", date ( "Y-m-d H:i:s" ) . "  " . $text . "\r\n", FILE_APPEND );
    }


    private function _execute($request){
        print_r('开发中');die;
        return $result;
    }


    /**
     * 获取随机码
     */
    private function getRandCode($num=16){
        $array=array(
            'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','U','W','X','Y','Z',
            'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','u','w','x','y','z',
            '1','2','3','4','5','6','7','8','9','0'
        );

        $temstr='';
        $max=count($array);
        for ($i=1;$i<=$num;$i++){
            $key=rand(0,$max-1);
            $temstr.=$array[$key];
        }
        return $temstr;
    }


    private function returnNotifyOne(){

        $postString=file_get_contents("php://input");
        libxml_disable_entity_loader(true);
        $xml=simplexml_load_string($postString,'SimpleXMLElement',LIBXML_NOCDATA);

        $xml_arr=[];
        foreach ($xml as $k=>$value){
            $xml_arr[$k]=trim(strval($value));
        }
        require \WxPayConfig::$PC_PAY_ONE_GET_ORDER;

        $pay_data['appid']=\WxPayConfig::$APPID; //公众账号ID 必填
        $pay_data['mch_id']=\WxPayConfig::$MCHID; //商户号 必填
        //$pay_data['sub_appid']='';  //子商户公众账号ID
        //$pay_data['sub_mch_id']=''; //子商户号

        //$pay_data['device_info']='';  //设备号 非必须
        $pay_data['nonce_str']=$this->getRandCode(32); //  随机字符串 必填


        $pay_data['body']=$order['body'];//商品描述  必填

        //$pay_data['detail']=$order_data['detail'];//商品详情  非必须
        $pay_data['attach']=$order['subject'];//附加数据  非必须
        $pay_data['out_trade_no']=$order['out_trade_no'];//商户订单号  必填
        //$pay_data['fee_type']='CNY';//货币类型  非必须
        $pay_data['total_fee']=$order['total_amount']*100;//总金额  必填

        $pay_data['spbill_create_ip']=$_SERVER['REMOTE_ADDR'];//终端IP  必填
        $pay_data['time_start']=date('YmdHis');//交易起始时间  必填
        //$pay_data['time_expire']=date('YmdHis');//交易结束时间  非必须
        //$pay_data['goods_tag']='WXG';//订单优惠标记  非必须

        //$pay_data['notify_url']=urldecode('http://webapp.lz4746.com/wxwechat/notify.php');//通知地址  必填
        $pay_data['notify_url']=urldecode(\WxPayConfig::$NOTIFY_URL);//通知地址  必填

        $pay_data['trade_type']='NATIVE';//交易类型  必填
        //$pay_data['limit_pay']='no_credit';//指定支付方式  非必须

        $pay_data['openid']=$xml_arr['openid'];//用户标识  必填
        // $pay_data['openid']='dddd';//用户标识  必填

        $pay_data['product_id']=$xml_arr['product_id'];//商品id


        //$pay_data['sub_openid']='';//用户子标识  非必须

        //$pay_data['scene_info']='';//场景信息  非必须
        //$pay_data['sign_type']='MD5'; //签名类型 非必须 默认MD5
        //

        ksort($pay_data);
        $stringA='';
        foreach ($pay_data as $k=>$v){
            $stringA.= $k.'='.$v.'&';
        }
        $stringA.='key='.\WxPayConfig::$KEY;

        $string=strtoupper(md5($stringA));
        //print_r($string);

        unset($pay_data['key']);
        $pay_data['sign']=$string;//签名  必填
       // print_r($pay_data);die;
        $xml_dat=""; //.PHP_EOL
        $xml_dat.="<xml>";
        foreach ($pay_data as $k=>$v){
            $xml_dat.="<".$k."><![CDATA[".$v."]]></".$k.">";
        }
        $xml_dat.="</xml>";

        $return_data=$this->httpPost('https://api.mch.weixin.qq.com/pay/unifiedorder',$xml_dat); //执行curl

        //将返回的结果xml结果转成数组
        libxml_disable_entity_loader(true);
        $return_data_obj=simplexml_load_string($return_data,'SimpleXMLElement',LIBXML_NOCDATA);

        $url_return_arr=[];
        foreach ($return_data_obj as $k=>$value){
            if(!in_array($k,['sign','trade_type','code_url'])){
                $url_return_arr[$k]=trim(strval($value));
            }
        }
        /**
         *  [return_code] => SUCCESS
        [return_msg] => OK
        [appid] => wxccce3033a624d942
        [mch_id] => 1487319022
        [nonce_str] => vHuqA2MdB9f5b9nb
        [sign] => 46D30694CB7E0C067388E95CF0B53F4D
        [result_code] => SUCCESS
        [prepay_id] => wx2812204677430774190bfcae4102477109
        [trade_type] => NATIVE
        [code_url] => weixin://wxpay/bizpayurl?pr=p3GItBi
         */

        $url_return_arr['appid']=\WxPayConfig::$APPID;
        $url_return_arr['mch_id']=\WxPayConfig::$MCHID;

        ksort($url_return_arr);

        $stringThree='';
        foreach ($url_return_arr as $k=>$v){
            $stringThree.= $k.'='.$v.'&';
        }
        $stringThree.='key='.\WxPayConfig::$KEY;

        $sign3=strtoupper(md5($stringThree));
        $url_return_arr['sign']=$sign3;
        ksort($url_return_arr);


        $return_xml_date='';
        $return_xml_date.="<xml>";
        foreach ($url_return_arr as $k=>$v){
            $return_xml_date.="<".$k."><![CDATA[".$v."]]></".$k.">";
        }
        $return_xml_date.="</xml>";

        echo $return_xml_date;


    }

    public function httpPost($url,$post_data){
        //初使化init方法
        $ch = curl_init();


        curl_setopt($ch, CURLOPT_URL, $url); //指定URL
        curl_setopt($ch, CURLOPT_POST, 1); //声明使用POST方式来进行发送
        curl_setopt($ch, CURLOPT_HTTPHEADER, Array("Content-Type:text/xml; charset=utf-8"));

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //设定请求后返回结果 获取的信息以文件流的形式返回
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); //发送什么数据呢

        //忽略证书
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);


        curl_setopt($ch, CURLOPT_HEADER, 0); //忽略header头信息
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置超时时间

        $output = curl_exec($ch); //发送请求
        curl_close($ch); //关闭curl

        //返回数据
        return $output;
    }

}